﻿using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace VisualProject;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    //旧绘制点和点击点之间的向量
    private Vector vector;
    //当前选中的小方块
    private DrawingVisual selectedVisual = null;
    //是否可以拖动
    private bool canDraging = false;
    //是否可以多选
    bool IsMulSelected = false;
    //多选框左上角坐标
    Point SelectedRectTopLeftPoint;
    //多选框可视化对象
    DrawingVisual selectedRect;
    private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        //获取鼠标点击相对于DrawingSurface的坐标
        Point mouseClickPoint = e.GetPosition(DrawingSurface);
       
        //选中RadioButton后执行各自的逻辑
        if (cmdAdd.IsChecked == true)
        {
          
            //实例化DrawingVisual对象
            DrawingVisual visual = new DrawingVisual();

            //绘制小方块
            DrawSquare(visual,mouseClickPoint,false);

            //添加到画布(通过DrawingVisual实例化visual对象，然后visual.RenderOpen开启一个DrawingContext绘制上下文进行绘制，绘制完了，传递给画布显示
            //这相当于DrawingVisual实例化的visual也是一个画布,visual.RenderOpen()开始一个DrawingContext是获得一个画笔，画笔绘制完了之后，再把
            //整个画布visual传递给DrawingCanvas显示,DrawingCanvas相当于一个展示框)
            
            DrawingSurface.AddVisual(visual);
        }
        if (cmdMove.IsChecked == true)
        {
            DrawingVisual visual = DrawingSurface.GetVisual(mouseClickPoint);
            if (visual != null)
            {
                //如果命中，那么就可以拖拽了
                canDraging = true;

                //如果selectedVisual是空的，或者selectedVisual不是当前命中的visual,那么就重新赋值
                if (selectedVisual == null || selectedVisual!=visual)
                {
                    //重绘原来选中的小方格
                    ClearSelectedVisual();
                    //设置新的选中的小方格
                    selectedVisual = visual;
                }
                //求出旧绘制点
                Point oldDrawingPoint = new Point(
                    selectedVisual.ContentBounds.TopLeft.X + pen.Thickness / 2,
                    selectedVisual.ContentBounds.TopLeft.Y + pen.Thickness / 2
                    );

                //计算一下旧绘制点和点击点之间的向量
                vector = mouseClickPoint - oldDrawingPoint;
                //新绘制点,新绘制点就是点击点-向量
                Point newDrawingPoint = mouseClickPoint - vector;
                //先重新绘制一下，设置为选中状态
                DrawSquare(selectedVisual, newDrawingPoint, true);

            }
        }
        if (cmdDelete.IsChecked == true)
        {
            //找到小方格
            DrawingVisual visual = DrawingSurface.GetVisual(mouseClickPoint);
            //删除小方格
            if (visual != null)
            {
                DrawingSurface.DeleteVisual(visual);
            }
        }

      
        if (cmdMulSelect.IsChecked == true)
        {
            //可以多选
            IsMulSelected = true;
            //记录点击的坐标,此坐标就是多选框左上角坐标
            SelectedRectTopLeftPoint = e.GetPosition(DrawingSurface);
            //创建多选框可视化实例
            selectedRect = new DrawingVisual();
            //放置到画布中(要放置在逻辑树和可视化树中，不然看不到)
            DrawingSurface.AddVisual(selectedRect);
            //捕获鼠标（这句代码 Mouse.Capture(DrawingSurface); 的核心作用是 “捕获鼠标输入”
            //让 DrawingSurface（绘图表面 / 控件）成为鼠标输入的 “唯一接收者”，
            //哪怕鼠标光标移出了这个控件的边界，后续的鼠标事件（如移动、点击、松开）依然会发送给它，直到主动释放捕获）
            Mouse.Capture(DrawingSurface);
        }

    }

    //定义画刷
    private Brush brush = Brushes.AliceBlue;
    //定义选中时画刷
    private Brush selectBrush = Brushes.LightGoldenrodYellow;
    //定义画笔
    private Pen pen = new Pen(Brushes.SteelBlue, 3);
    //定义小方格大小
    private Size size = new Size(30, 30);
    //绘制小方块方法
    private void DrawSquare(DrawingVisual visual,Point point,bool IsSelected)
    {
        //visual.RenderOpen获取设备上下文
        using(DrawingContext dc = visual.RenderOpen())//using 自动释放dc,不需要写dc.Close()了
        {
            //设置默认画刷
            Brush DrawingBrush = brush;
            //如果小方格被选中，那么画刷颜色改变(填充颜色)
            if (IsSelected == true)
            {
                DrawingBrush = selectBrush;
            }

            //设备上下文dc，绘制矩形
            dc.DrawRectangle(DrawingBrush, pen, new Rect(point, size));
        }
    }

    private void DrawingSurface_MouseMove(object sender, MouseEventArgs e)
    {
        if (canDraging)
        {
            //移动点坐标
            Point movePoint = e.GetPosition(DrawingSurface);
            //新绘制点坐标
            Point newDrawingPoint = movePoint - vector;
            //重新绘制
            DrawSquare(selectedVisual, newDrawingPoint, true);
        }

        if (IsMulSelected)
        {
            //移动点就是多选框右下角坐标
            Point selectedRectBottomRightPoint = e.GetPosition(DrawingSurface);

            //画多选框
            DrawSelectedRect(SelectedRectTopLeftPoint, selectedRectBottomRightPoint);

        }
    }
    //设置多选框画刷
    Brush selectedRectBrush = Brushes.Transparent;
    //设置多选框画笔
    Pen selectedRectPen = new Pen(Brushes.Black, 2);
    //画多选框函数
    private void DrawSelectedRect(Point point1,Point point2)
    {
        //设置画笔样式
        selectedRectPen.DashStyle = DashStyles.Dash;

        using(DrawingContext dc = selectedRect.RenderOpen())
        {
            dc.DrawRectangle(selectedRectBrush, selectedRectPen, new Rect(point1, point2));
        }
    }
    private void DrawingSurface_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        //鼠标左键松开后，禁止拖拽
        if (canDraging)
        {
            canDraging = false;
        }

        //当有多选的时候,禁止多选(如果不进行判断，可能会有这样的情况:鼠标在DrawingSurface外面点击了，然后在DrawingSurface
        //内部松开，那么此时IsMulSelected=false,没有执行DrawingSurface的鼠标左键点击事件，直接执行了这里的松开事件，那么可能
        //错误产生，所以这里我们必须确保，必须是在DrawingSurface中点击了，IsMulSelected==true，我们松开后才执行这里的代码）
        if (IsMulSelected)
        {
            //禁止多选
            IsMulSelected = false;
            //创建命中参数(会在这个矩形内部进行命中测试)
            Rect rect = new Rect(SelectedRectTopLeftPoint, e.GetPosition(DrawingSurface));
            RectangleGeometry geometry = new RectangleGeometry(rect);

            //删除多选框(在逻辑树和视觉树中删除,还有在DrawingSurface的子元素中删除)
            //在进行命中测试之前删除,不然selectedRect也会被进行命中测试，会使命中结果永远多出一个(在视觉树中的都会被进行命中测试)
            DrawingSurface.DeleteVisual(selectedRect);
            //获取多选框(就是这个geometry)内部的小方格
            List<DrawingVisual> visuals= DrawingSurface.GetVisuals(geometry);
            //提示
            MessageBox.Show($"选中了{visuals.Count()}个小方块");
          
            //释放捕获
            Mouse.Capture(null);
        }
     

     
    }

    //清除原来选中的小方格
    private void ClearSelectedVisual()
    {
        if (selectedVisual != null)
        {
            //求出绘制点
            Point DrawingPoint = new Point(
                selectedVisual.ContentBounds.TopLeft.X + pen.Thickness / 2,
                selectedVisual.ContentBounds.TopLeft.Y + pen.Thickness / 2
                );
            //重新绘制
            DrawSquare(selectedVisual, DrawingPoint, false);
        }
       
    }
}